<?php

/*//. basic local only socket server.
  ../ idea 1 for multiplatform instance management.
  ../ this will allow additional commands to be executed and the program will
  ../ attempt to find an already running instance.
  
  ../ i make no claims about any security flaws in this. as the bsd license
  ../ states... use at your own peril i don't take responsiblity for your
  ../ system getting exploded.
.//*/

class jennyServer {

	public $remote;
	public $local;
	
	static $debug = false;
	static function debugmsg($msg) {
		if(self::$debug) {
			echo($msg);
		} return;
	}

	public function __construct() {

		if(bob::$config->get('force-server') || !$this->anotherServerRunning()) {
			self::debugmsg("no servers detected\n");
			$this->startServer();
		} else {
			self::debugmsg("server found\n");
			$this->sendFileList();
			fwrite($this->remote,"bai bai\n");
			stream_socket_shutdown($this->remote,STREAM_SHUT_RDWR);
			bob::endProgram();
		}

	}
	
	public function sendFileList() {
		stream_set_timeout($this->remote,false);
		foreach(bob::$cmd['file-open'] as $file) {
			fwrite($this->remote,"enjoy {$file}\n");
			$recv = trim(fgets($this->remote));
		} return;
	}
	
	public function anotherServerRunning() {
		$port = (int)bob::$config->get('current-instance');
		if(!$port) { return false; }
		
		self::debugmsg("attempting to raise server on port {$port}\n");
		$client = stream_socket_client("udp://localhost:{$port}");
		stream_set_blocking($client,true);
		stream_set_timeout($client,false);
		
		fwrite($client,sprintf("hello jenny%s\n",md5($port)));
		$recv = trim(fgets($client));
		if($recv && $recv == 'hai2u') {
			self::debugmsg("server found.\n");
			$this->remote = $client;
			return true;
		}
		
		self::debugmsg("no server found\n");
	
		return false;
	}
	
	public function startServer() {
		/*//. pick random ports and keep trying until we open a server on
		  ../ one. then save the connection data to the config file and
		  ../ listen on it. .//*/

		self::debugmsg("launching server\n");

		do {
			$port = rand(1024,65465);
		} while(!(bob::$server = $this->attemptBind($port)));
		
		self::debugmsg("server launched with port {$port}\n");
		
		stream_set_timeout(bob::$server,false);
		Gtk::io_add_watch(bob::$server,BOB_IO_IN,array($this,'recv'));
		
		bob::$config->set('current-instance',$port);
		bob::$config->save();
		return;
	}
	
	public function attemptBind($port) {
		return stream_socket_server(
			"udp://localhost:{$port}",
			$errno, $errstr,
			STREAM_SERVER_BIND
		);
	}
	
	public function recv($stream) {
	
		if(!($pos = strpos(stream_socket_recvfrom(bob::$server,1024,STREAM_PEEK),chr(10)))) {
			return true;
		} $pos++;
	
		$recv = stream_socket_recvfrom(bob::$server,$pos,null,$from);
		self::debugmsg("recv from {$from}: $recv");
		
		list($address,$port) = explode(':',$from);
		preg_match('/([^\s]+) (.+)/',trim($recv),$match);
		$msg = $match[1];
		$data = $match[2];
		
		switch($msg) {
			case('hello'): {
				if($data == sprintf('jenny%s',md5(bob::$config->get('current-instance')))) {
					self::debugmsg("valid client found\n");
					stream_socket_sendto(bob::$server,"hai2u\n",0,$from);
					break;
				}
				break;
			}
			case('enjoy'): {
				$w = current(bob::$winReg);
				$w->openFile($data);
				stream_socket_sendto(bob::$server,"kthx\n",0,$from);
				break;
			}
			case('bai'): {
				$w = current(bob::$winReg);
				$w->present();
				break;
			}
		}
		
		return true;
	}
}

?>